package cn.kgc.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.kgc.entity.Resume;
import cn.kgc.entity.TccRecord;
import cn.kgc.mapper.ResumeMapper;
import cn.kgc.service.ResumeTccService;
import cn.kgc.service.TccRecordService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author YC
 */
@Service("resumeTccService")
@Slf4j
public class ResumeTccServiceImpl implements ResumeTccService {

    @Resource
    private ResumeMapper resumeMapper;
    @Resource
    private TccRecordService tccRecordService;

    @Override
    public boolean tryInitResume(BusinessActionContext actionContext, String userId) {
        // BusinessActionContextParameter注解，获取全局事务ID和分支事务ID
        String xid = actionContext.getXid();
        String branchId = String.valueOf(actionContext.getBranchId());
        if (StrUtil.isBlank(xid) || StrUtil.isBlank(branchId)) {
            log.warn("全局事务ID或分支事务ID为空");
            return false;
        }
        // 判断是否已经执行过try操作，是则不能执行try操作（保证幂等性），否则继续
        if (tccRecordService.hasTry(xid, branchId)) {
            log.warn("全局事务{}下的分支事务{}，已经执行过try操作，不能重复执行", xid, branchId);
            return false;
        }
        // 判断是否已经执行过cancel操作，是则不能执行try操作（防止业务悬挂），否则继续
        if (tccRecordService.hasCancel(xid, branchId)) {
            log.warn("全局事务{}下的分支事务{}，已经执行过cancel操作，不能执行try操作", xid, branchId);
            return false;
        }
        // 执行try操作（初始化简历信息）,并记录try操作日志
        Resume resume = Resume.builder().userId(userId).build();
        resumeMapper.insert(resume);
        tccRecordService.save(
                TccRecord.builder().status((short) 1).xid(xid).branchId(branchId).actionName("tryInitResume")
                        .args(JSONUtil.toJsonStr(new String[]{userId})).build()
        );
        return true;
    }

    @Override
    public boolean commitInitResume(BusinessActionContext actionContext) {
        // commit操作可以为空，返回值一定为true，否则TCC会不断重复调用commit方法
        return true;
        // 如果不为空，执行以下逻辑：
        // 1.判断是否已经执行过commit操作，是则不能执行commit操作（保证幂等性），否则继续
        // 2.执行commit操作（初始化简历信息），更改TCC_RECORD中当前事务的状态为commit，并记录commit操作日志
    }

    @Override
    public boolean cancelInitResume(BusinessActionContext actionContext) {
        // BusinessActionContextParameter注解，获取全局事务ID和分支事务ID
        String xid = actionContext.getXid();
        String branchId = String.valueOf(actionContext.getBranchId());
        String userId = actionContext.getActionContext("userId").toString();
        // 判断是否已经执行过cancel操作，是则不能执行cancel操作（保证幂等性），否则继续
        if (tccRecordService.hasCancel(xid, branchId)) {
            log.warn("全局事务{}下的分支事务{}，已经执行过cancel操作，不能重复执行", xid, branchId);
            // 返回值一定为true，否则TCC会不断重复调用cancel方法
            return true;
        }
        // 判断是否已经执行过try操作，是则继续，否则不能先执行分支事务的cancel操作（防止空操作回滚）。可以记录cancel操作日志
        if (!tccRecordService.hasTry(xid, branchId)) {
            log.warn("全局事务{}下的分支事务{}，没有执行过try操作，不能执行cancel操作", xid, branchId);
            return tccRecordService.save(
                    TccRecord.builder().status((short) 3).xid(xid).branchId(branchId).actionName("cancelInitResume")
                            .args(JSONUtil.toJsonStr(new String[]{userId})).build()
            );
        }
        // 执行cancel操作（删除简历信息），更改TCC_RECOR表中当前事务的状态为cancel，并记录cancel操作日志
        resumeMapper.delete(new LambdaQueryWrapper<Resume>().eq(Resume::getUserId, userId));
        return tccRecordService.update(
                new LambdaUpdateWrapper<TccRecord>().eq(TccRecord::getXid, xid).eq(TccRecord::getBranchId, branchId)
                        .set(TccRecord::getStatus, (short) 3)
        );
    }

}
